perm filename MEMTST.PAL[11,SYS] blob sn#604747 filedate 1981-08-12 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00008 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	.TITLE Memory Diagnostic
C00008 00003	First initialize the mapper
C00013 00004	Control loop for tests
C00016 00005	Now lets do some tests!
C00022 00006	Error trap handlers: NXM, MPRTRP, PARERR
C00025 00007	ERROR, SETMAP & I/O Routines
C00030 00008	Constants & Data
C00033 ENDMK
C⊗;
.TITLE Memory Diagnostic
			;written by ARG 7/77 - modified for regular memory 7/79
COMMENT ⊗ This is a program to test out the memory on the PDP 11/45.
There are 6 tests. Four write a given pattern into memory and then read it back.
The patterns are all zeros, all ones, and two checkerboard patterns. The next two
tests check out the addressing by writing the address of each location, or the
complement of the address, in that location. The regular addresses are written
in ascending order, while the complements are written in descending order. 

Each test can be explicitly specified or the first 6 can be cycled through
automatically. Which 8K chunk of the 64K memory is to be used can also
be explicitly chosen or all 8 chunks can be cycled through.

When an error is encountered the program types out the memory's address, the
value that was expected, and the value read. R5 contains the virtual address of
the bad location. The program can be told to break to DDT when an error occurs.
A count of the errors encountered is kept and it may be displayed. It is also
possible to suppress error print out.

At the conclusion of each test or test cycle a counter is incremented and displayed
showing the number of tests performed. It is possible to break to DDT upon
completion of the test in progress.

Control of the program is accomplished by use of the front panel switches as
shown below:

   _________________________________________________________________________
   |       |   |   |       |           |   |   |   |       |   |           |
   |       |   |   |       |           |loop   break      select           |
   |       |run|display    |  test #   |on type| to|       | or|  which 8K |
   |       | or|   |       |           |   |out|DDT|       cycle           |
   |       |DDT|   |       |   (0-6)   error   | on|       |mem|   (0-7)   |
   |       |   |   |       |           |   |   error       |   |           |
   | X   X |   |   | X   X |           |   |   |   | X   X |   |           |
   |___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|
    17  16  15 |14  13	12 |11  10   9 | 8   7   6 | 5   4   3 | 2       0 
   

Explanation of switch settings:

	Run/DDT - if up break to DDT at completion of current test
	display - if up display # of errors in lights, else display the number
			of tests performed (iteration count)
	test #  - number from 0 to 6 to select test:
			0 cycle through tests 1-6
			1 write all zeros
			2 write all ones
			3 write checkerboard 0101...
			4 write checkerboard 1010...
			5 addresses (ascending)
			6 complement of addresses (descending)
	loop on error - if switch 8 is up, loop on error for tests 1 - 4.
	typeout - if switches 6 & 7 are both down then no typeout is printed
			if either is up then error messages are typed
	break to DDT on errors - if up does just that
	select/cycle - if up selects 8K chunk specified by last three switches
			if down cycles through all eight chunks

Typing any character while errors are being typed out will cause the 11 to go
into a hold on output until another character is typed.

⊗
;First initialize the mapper

.INSRT STUFF.PAL[11,ARG]
.INSRT MAPPER.PAL[AL,HE]

LOW= 100000		;Memory gets mapped from 100 000 to 137 777
HI = 140000

.=4
	NXM
	340
.=114			;PARITY ERROR TRAP
	PARERR
	340
.=250
	MPRTRP
	340
.=1000

START:	RESET
	MOV #START,SP		;Set up the stack
	MOV #BEGMES,R1		;Tell world who we are
	JSR PC,OUTSTR
	MOV #CRLF,R1
	JSR PC,OUTSTR

;  Set up the four page tables

	;	Virtual address			Physical address
	;	    0 -  77777      Core	     0 -   7777
	;      100000 - 137777  Memory to test	100000 - 137777
	;      140000 - 157777      unused
	;      160000 - 177777      I/O		760000 - 777777


PINIT:  MOV #KISDR0,R1		;Set up Kernel's Page Descriptor Registers
	MOV #20,R0		;do both I & D spaces - 8 registers each
1$:	MOV #MAPRW+MAPPLF,(R1)+	;Read/Write - full size {4K = 200 blocks}
	SOB R0,1$	

	MOV #PGTBL0,R1		;Map 0, transparent
	MOV #KISAR0,R2
	MOV #KDSAR0,R3
	MOV #10,R0		;Set up Kernel I & D space mappings
2$:	MOV (R1),(R2)+
	MOV (R1)+,(R3)+
	SOB R0,2$

	MOV #7,MAPSR3		;Enable I & D spaces
	MOV #MAPENB,MAPSR0	;Turn the map on 

;Control loop for tests

	MOV #5,TEST		;Initialize some values
	MOV #7,CHUNK
	CLR ERRNUM		;Zero error count
	CLR PARNUM		;Zero parity error count
	CLR ITER		;Zero count of # times through

TLOOP:	BIT #10,@VSW		;Select one 8K chunk or cycle through?
	BEQ 1$
	MOV @VSW,CHUNK		;Get selected 8K chunk
	BIC #177770,CHUNK
	BR 4$
1$:	BIT #7000,@VSW		;Are we cycling through tests too?
	BEQ 3$
2$:	INC CHUNK		; No - test next chunk
	BIC #10,CHUNK
	BR 4$
3$:	CMP #5,TEST		; Yes - only move to next 8K chunk if #test = 5
	BLE 2$
4$:	JSR PC,SETMAP		;Select the proper 8K chunk

	MOV @VSW,R0		;See what test we're to do
	ASH #-11,R0		;Move test # to low 3 bits - shift right 9
	BIC #177770,R0
	BNE 6$			;Skip ahead & jump to selected test, unless cycling
	MOV TEST,R0		;Get # of last test done
	INC R0			;Do next one
	CMP #6,R0
	BGT 5$
	CLR R0			;Only cycle through first 6 tests
5$:	INC R0
6$:	DEC R0			;Correct for table
	MOV R0,TEST		;Remember it
	ROL R0			;Offset in words
	JSR PC,@TESTS(R0)	;Go do test

	MOV @VSW,R0		;Get test #
	ASH #-11,R0
	INC R0
	BIC #177770,R0
	BEQ 8$			;Update ITER count if test # = 7
	BIT #7000,@VSW		;See if it's time to update ITER count
	BNE 7$			;Cycling through tests?
	CMP #5,TEST		; If so don't update ITER unless #test = 5
	BGT 9$
7$:	BIT #10,@VSW		;Cycling through memory
	BNE 8$			;If not go increment ITER
	CMP #7,CHUNK		; else only if CHUNK = 7
	BNE 9$
8$:	INC ITER
9$:	MOV ITER,R0
	BIT #40000,@VSW		;Who to display?
	BEQ 10$			; Display # times through
	MOV ERRNUM,R0		; Display # errors
10$:	MOV R0,%SWR

	BIT #100000,@VSW	;Keep running
	BEQ 11$
	BPT			; Or break to DDT
11$:	JMP TLOOP		;Repeat it all again

;Now lets do some tests!

TEST1:	CLR R4			;Write and read all zeros
	JMP PATTST

TEST2:	MOV #177777,R4		;Write and read all ones
	JMP PATTST

TEST3:	MOV #052525,R4		;The two checkerboard patterns: 0101010101010101
	JMP PATTST

TEST4:	MOV #125252,R4		; & 1010101010101010 (these test noise immunity)
	JMP PATTST


PATTST:	MOV #LOW,R5		;Auxiliary routine for tests 1-4
	CLR WRTRD		;Indicate we're writing
P1:	MOV R4,(R5)+		;Write pattern
	CMP R5,#HI		;See if done
	BLO P1			;No - keep looping
	MOV #LOW,R5
	INC WRTRD		;Indicate we're reading
	mov #2,r2		;TED
P2:	MOV (R5),R3		;Read pattern
	CMP R4,R3		; & check it
	BEQ 3$			;If ok skip ahead
	JSR PC,ERROR		; else call the error routine
	BPT			; & break to DDT
	mov #2,r2		;TED
	bit #400,@VSW		;TED - loop on error?
	beq 2$			;TED 
	clr r2			;TED - set loop flag
2$:	bit #100000,@VSW	;TED - get out?
	bne 4$
3$:	add r2,r5		;TED - are we looping on error?
	CMP R5,#HI		;See if done with this 8K
	BLO P2			;No - keep looping
4$:	RTS PC

PATERR: ADD #2,R5		;Keep going with next word
	CMP R5,#HI
	BLO 1$			; & then resume testing
	RTS PC			; but don't go too far - return if done
1$:	TST WRTRD		;Where were we when the parity error zapped us?
	BNE P2			;Reading
	BR P1			;Still writing

	;This test writes the address of each location in that location.
	;First we write all the addresses and then we read them.
	;This and the next test confirm that each address accesses a unique location

TEST5:	MOV #LOW,R5
	CLR WRTRD		;Indicate we're writing
T51:	MOV R5,(R5)+		;Write the location's address (ascending)
	CMP R5,#HI		;See if done
	BLO T51			;No - keep looping
	MOV #LOW,R5
	INC WRTRD		;Indicate we're reading
T52:	MOV (R5),R3		;Read value
	CMP R5,R3		;Check that location has correct value
	BEQ 3$
	MOV R5,R4		;So error routine knows what value was expected
	JSR PC,ERROR		;Call error routine
	BPT			; & break to DDT
3$:	ADD #2,R5		;Next address to check
	CMP R5,#HI		;See if done
	BLO T52			;No - keep looping
	RTS PC

T5ERR:	ADD #2,R5		;Keep going continuing with next word
	CMP R5,#HI
	BLO 1$			; but don't go too far
	RTS PC			; return if done
1$:	TST WRTRD		;Where were we when the parity error zapped us?
	BNE T52			;Reading
	BR T51			;Still writing


	;As above but write the complement of each address and work from the high
	;to the low addresses

TEST6:	MOV #HI-2,R5
	CLR WRTRD		;Indicate we're writing
T61:	MOV R5,R4		;Write the complement of the location's address
	COM R4
	MOV R4,(R5)
	SUB #2,R5		;Point to next word (descending)
	CMP R5,#LOW		;See if done
	BHIS T61		;No - keep looping
	MOV #HI-2,R5
	INC WRTRD		;Indicate we're reading
T62:	MOV R5,R4		;Get complement of address in R4
	COM R4
	MOV (R5),R3		;Read value
	CMP R4,R3		;Check that location has correct value
	BEQ 3$
	JSR PC,ERROR		;Call error routine
	BPT			; & break to DDT
3$:	SUB #2,R5		;Next address to check
	CMP R5,#LOW		;See if done
	BHIS T62		;No - keep looping
	RTS PC

T6ERR:	SUB #2,R5		;Keep going continuing with next word
	CMP R5,#LOW
	BHIS 1$			; but don't go too far
	RTS PC			; return if done
1$:	TST WRTRD		;Where were we when the parity error zapped us?
	BNE T62			;Reading
	BR T61			;Still writing

;Error trap handlers: NXM, MPRTRP, PARERR

NXM:	MOV #NXMMES,R1		;Print nxm error message
	BR TRP
MPRTRP:	MOV #MAPMES,R1		;Print map trap error message
TRP:	JSR PC,OUTSTR
	MOV CHUNK,R0		;Get high 3 bits of memory address
	BIC #177770,R0
	MOV R5,R1		;Get low 14 bits
	SUB #LOW,R1		;Get rid of offset
	ASH #2,R1		;Shift low 14 bits over 2 to the left
	ASHC #-1,R0		;Shift all 17 bits over 1 to the right
;	ADD #'0,R0		;Print the high 2 bits - 0-64K offset
	ADD #'1,R0		;Print the high 2 bits - actual unibus address
	JSR PC,OUTCHR
	JSR PC,OUTNM1		;& then print the low 15 bits
	MOV #CRLF,R1
	JSR PC,OUTSTR		;Skip a line
TRPRET:	RTI		;*** for NXM debugging ***
	MOV 16,PS		;Now make it look like the bad instruction
	JMP @14			; did a BPT to DDT

PARERR:	INC PARNUM		;Update # of parity errors encountered
	MOV #ERR1P,R1		;Print "parity error"
	JSR PC,OUTSTR
	JSR PC,ERROR		;Call error routine to print info (?)
	SEC			;no-op - break to DDT if desired later
PARRET: MOV #1,PARCSR		;Re-enable parity trapping
	MOV #CRLF,R1		;Parity trap return code
	JSR PC,OUTSTR
	ADD #4,SP		;Clean up stack (error routines can still use PC)
	BIT #200,%TKS		;SOMEBODY TYPED SOMETHING?
	BEQ 6$
	JSR PC,HOLD
	TST %TKB		;CLEAR READY FLAG
5$:	BIT #200,%TKS		;SOMEBODY TYPED SOMETHING?
	BEQ 5$
	JSR PC,UNHOLD
	TST %TKB		;CLEAR READY FLAG

6$:	BIT #100,@VSW		;Break to DDT on errors?
	BEQ 7$
	BPT			;Yes - go to DDT
7$:	MOV TEST,R0		;Get # of current test
	ROL R0
	JMP @TSTERR(R0)		;Go to the appropriate error entry for this test

;ERROR, SETMAP & I/O Routines

ERROR:	INC ERRNUM		;Update error count
	BIT #300,@VSW		;See if typeout or break to DDT on errors set
	BEQ 1$
	MOV #ERR1,R1		;Print "Error at address:"
	JSR PC,OUTSTR
	MOV CHUNK,R0		;Get high 3 bits of memory address
	BIC #177770,R0
	MOV R5,R1		;Get low 14 bits
	SUB #LOW,R1		;Get rid of offset
	ASH #2,R1		;Shift low 14 bits over 2 to the left
	ASHC #-1,R0		;Shift all 17 bits over 1 to the right
;	ADD #'0,R0		;Print the high 2 bits - 0-64K offset
	ADD #'1,R0		;Print the high 2 bits - actual unibus address
	JSR PC,OUTCHR
	JSR PC,OUTNM1		;& then print the low 15 bits
	MOV #ERR2,R1		;Print "Value should be:"
	JSR PC,OUTSTR
	MOV R4,R1		;Print the expected value
	JSR PC,OUTNUM
	MOV #ERR3,R1		;Print "But was:"
	JSR PC,OUTSTR
	MOV R3,R1		;Print the real value
	JSR PC,OUTNUM
	mov #err5,r1		;print "test#"
	jsr pc,outstr
	mov test,r0		;print test#
	add #61,r0
	jsr pc,outchr
	MOV #CRLF,R1		;Skip a line
	JSR PC,OUTSTR
	BIT #200,%TKS		;SOMEBODY TYPED SOMETHING?
	BEQ 1$
	JSR PC,HOLD
	TST %TKB		;CLEAR READY FLAG
4$:	BIT #200,%TKS		;SOMEBODY TYPED SOMETHING?
	BEQ 4$
	JSR PC,UNHOLD
	TST %TKB		;CLEAR READY FLAG

1$:	BIT #100,@VSW		;Break to DDT on errors?
	BNE 2$
	ADD #2,(SP)		;If not skip over the BPT following the JSR to ERROR
2$:	BIT #40000,@VSW		;Should we display the new error count
	BEQ 3$
	MOV ERRNUM,%SWR		;Display error count in lights
3$:	RTS PC

HLDMS:	.BYTE 16
	.BYTE 40
.REPT 4
	.BYTE 200	;FILLER FOR 2400 BAUD
.ENDR
	.BYTE 40
	.ASCII /****HOLDING****/
	.BYTE 36
	.BYTE 16
	.BYTE 63
.REPT 4
	.BYTE 200	;FILLER FOR 2400 BAUD
.ENDR
	.BYTE 40
	.BYTE 0
	.EVEN

UHLDMS:	.BYTE 16
	.BYTE 40
.REPT 4
	.BYTE 200	;FILLER FOR 2400 BAUD
.ENDR
	.BYTE 40
	.BYTE 36
	.BYTE 16
	.BYTE 63
.REPT 4
	.BYTE 200	;FILLER FOR 2400 BAUD
.ENDR
	.BYTE 40
	.BYTE 0
	.EVEN

SETMAP:	MOV CHUNK,R1		;Get which 8K to map to
	MUL #400,R1		;Compute physical address of chunk
	ADD #1000,R1		; adding in an offset of 100000
	MOV R1,KDSAR0+10	;V.Loc 100000 to 117777 goes to P.Loc of chunk
	ADD #200,R1
	MOV R1,KDSAR0+12	;ditto for V.Loc 120000 to 137777
	RTS PC

UNHOLD:	MOV #UHLDMS,R1
	BR OUTSTR

HOLD:	MOV #HLDMS,R1
OUTSTR:	MOVB (R1)+,R0		;Get next char
	BEQ 1$			;If done - quit
	JSR PC,OUTCHR		;Print it
	BR OUTSTR
1$:	JSR PC,OUTCHR		;Print a couple nulls
	JSR PC,OUTCHR
	JMP OUTCHR


OUTNUM:	CLR R0
	ASHC #1,R0		;Get high bit
	ADD #'0,R0		;Convert it to ASCII
	JSR PC,OUTCHR		; & print it
OUTNM1:	MOV R2,-(SP)
	MOV #5,R2		;Get low 5 digits
OUTNM2:	CLR R0
	ASHC #3,R0		;Get next digit
	ADD #'0,R0		;Convert it to ASCII
	JSR PC,OUTCHR		; & print it
	SOB R2,OUTNM2		;Do it all
	MOV (SP)+,R2
	RTS PC
OUTNMN:	MOV R2,-(SP)		;Entry point for only a few digits, # in R1
	MOV R0,R2
	BR OUTNM2


OUTCHR:	TST OUTSW		;Who does it go to?
	BEQ 2$
1$:	TSTB KBOS		;VT05 ready?
	BPL 1$			;Loop til it is
	MOVB R0,KBOR		;Print the char
	RTS PC
2$:	TSTB OREG		;Console ready?
	BNE 2$			;Wait til it is
	MOVB R0,OREG		;Output char
	RTS PC

;Constants & Data

PARNUM: 0		;Number of parity errors
ERRNUM:	0		;Number of errors
ITER:	0
CHUNK:	7
TEST:	5
WRTRD:	0		;Writing (0) or reading (1)
VSW:	SW		;So I can run this from home without having to worry

PGTBL0: .WORD 0,200,400,600,1000,1200,1400,7600

TESTS:	TEST1		;Write all zeros
	TEST2		;      all ones
	TEST3		;      0101...
	TEST4		;      1010...
	TEST5		;      addresses (ascending)
	TEST6		;      complement of addresses (descending)
	TEST1		;Until something better comes along for test #7

TSTERR:	PATERR		;Write all zeros
	PATERR		;      all ones
	PATERR		;      0101...
	PATERR		;      1010...
	T5ERR		;      addresses (ascending)
	T6ERR		;      complement of addresses (descending)
	PATERR		;Until something better comes along for test #7
 

	;Now all those ASCII strings for the various messages

BEGMES:	.ASCII /πMemory diagnostic program (did you set core to 16K?)/
CRLF:	.BYTE 12,15,0
NXMMES:	.ASCIZ /πNXM at: /
MAPMES:	.ASCIZ /πMapper error at: /
ERR1:	.ASCIZ /πError address: /
ERR2:	.ASCIZ /  Correct: /
ERR3:	.ASCIZ /  Error: /
err5:	.asciz /  test# /
ERR1P:	.ASCIZ /πParity error - we lose big since this memory doesn't generate them!!
/
.EVEN

SETOM:	MOV #LOW,R1	;random routine to call from ddt
SETOM1:	MOV #-1,(R1)+
	CMP R1,#HI
	BLO SETOM1
	BPT

patch:	.blkw 100

	.END START